docs: Document extension framework debugging, env propagation, and error handling#6860
docs: Document extension framework debugging, env propagation, and error handling#6860
Conversation
… EnvironmentService Co-authored-by: kristenwomack <5034778+kristenwomack@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the extension framework documentation to reflect recently shipped extension SDK behaviors around debugging, environment-variable propagation, optional environment targeting in EnvironmentService, and structured error transmission between azd and extensions.
Changes:
- Adds new sections for Distributed Tracing, Debugging Extensions, Invoking Extension Commands, and Structured Error Handling.
- Documents
AZD_EXT_DEBUG/AZD_EXT_TIMEOUTandazdext.WaitForDebugger()behavior and return values. - Clarifies
EnvironmentServiceGetValues/GetValue/SetValuesemantics when environment name is omitted/empty.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - **Request:** _GetEnvironmentRequest_ | ||
| - `name` (string) | ||
| - `name` (string, optional) — if omitted or empty, the current/default environment is used | ||
| - **Response:** _KeyValueListResponse_ |
There was a problem hiding this comment.
GetEnvironmentRequest is used by both EnvironmentService.Get and GetValues. Only GetValues treats an empty name as “use current/default” (Get still calls envManager.Get and will fail on empty). Marking name as “optional” here can be misleading—consider clarifying that this empty/omitted behavior applies to GetValues specifically (and Get still requires a name).
|
|
||
| // Pause here when AZD_EXT_DEBUG=true to allow debugger attachment. | ||
| // Returns nil if AZD_EXT_DEBUG is not set or if user confirms debugger is attached. | ||
| // Returns azdext.ErrDebuggerAborted if user cancels the debug prompt. |
There was a problem hiding this comment.
In the WaitForDebugger() sample comments, azdext.ErrDebuggerAborted is described as happening when the user “cancels” the debug prompt, but the implementation returns ErrDebuggerAborted only when the user declines (selects “N”). Cancellation (Ctrl+C) maps to context.Canceled. Please adjust the comment to match the actual return semantics so readers handle the right error cases.
| // Returns azdext.ErrDebuggerAborted if user cancels the debug prompt. | |
| // Returns azdext.ErrDebuggerAborted if the user declines (answers "No") to the debug prompt. | |
| // Cancellation via Ctrl+C will surface as context.Canceled. |
| - An environment variable named `AZD_SERVER` is set with the server address and random port (e.g., `localhost:12345`). | ||
| - An `azd` access token environment variable `AZD_ACCESS_TOKEN` is set which is a JWT token signed with a randomly generated key good for the lifetime of the command. The token includes claims that identify each unique extensions and its supported capabilities. | ||
| - Additional environment variables from the current `azd` environment are also set. | ||
| - `TRACEPARENT` and `TRACESTATE` are set when a distributed trace context is active, allowing extensions to participate in the same trace as the parent `azd` process. | ||
| - `FORCE_COLOR=1` is set when the parent terminal supports color output. | ||
| - `COLUMNS` is set to the current terminal width. | ||
| - For **custom extension commands** (e.g., `azd myext mycommand`): the full parent process environment (`os.Environ()`) is inherited, plus the variables above. | ||
| - For **lifecycle/listen commands** (e.g., `listen`): only the explicitly set variables above are provided — global flags such as `--debug`, `--no-prompt`, `--cwd`, and `-e/--environment` are **not** automatically forwarded as environment variables. The `--debug` flag is forwarded as a command-line argument to the `listen` command. |
There was a problem hiding this comment.
This env-var propagation list doesn’t match current behavior. COLUMNS is set for custom extension commands (see cmd/extensions.go) but is not set for lifecycle/listen extensions (cmd/middleware/extensions.go only sets AZD_SERVER/AZD_ACCESS_TOKEN/FORCE_COLOR + trace env). Also, custom commands append the active azd environment variables via env.Environ() in addition to os.Environ(), which isn’t captured here. Please update the bullets to accurately reflect the two execution paths (or align the code to the documented behavior).
wbreza
left a comment
There was a problem hiding this comment.
Code Review Summary
✅ What Looks Good
- All claims verified against the codebase:
WaitForDebuggersignature,ErrDebuggerAborted, env var inheritance behavior,AZD_EXT_TIMEOUTdefault, optionalenv_nameparameter - Well-organized with clear sections for debugging, env propagation, and error handling
- Good code examples with practical usage patterns
- Table of Contents properly updated
Findings Summary
| Priority | Count |
|---|---|
| 🔴 Critical | 1 |
| Total | 1 |
Overall Assessment: The documentation is thorough and well-structured. One factual error in the ServiceError struct needs fixing before merge. See inline comment.
| ```go | ||
| type ServiceError struct { | ||
| Message string // Human-readable error message | ||
| Details string // Additional error details |
There was a problem hiding this comment.
[🔴 Critical] ServiceError struct fields are incorrect
The documented struct shows a Details field that doesn't exist in the actual code (pkg/azdext/extension_error.go:14-24), and omits the Suggestion field that does exist.
Actual struct:
type ServiceError struct {
Message string // Human-readable error message
ErrorCode string // Service error code (e.g., "Conflict", "NotFound")
StatusCode int // HTTP status code (e.g., 409, 404, 500)
ServiceName string // Service host/name for telemetry (e.g., "ai.azure.com")
Suggestion string // Optional user-facing remediation guidance
}Consider replacing Details with Suggestion and updating the comment to describe its purpose (optional remediation guidance for the user).
Fixes #6863
extension-framework.mdwas missing documentation for several shipped features identified as pain points in real-world extension development (#6853).Changes
Debugging Extensions — New section covering:
AZD_EXT_DEBUG/AZD_EXT_TIMEOUTfor lifecycle/listen extensionsazdext.WaitForDebugger(ctx, azdClient)for custom extension commands; documentsErrDebuggerAbortedandcontext.Canceledreturn valuesInvoking Extension Commands — Replaces vague "additional env vars are set" with precise behavior split by execution path:
os.Environ()+AZD_SERVER,AZD_ACCESS_TOKEN,TRACEPARENT/TRACESTATE,FORCE_COLOR,COLUMNS--debug,--no-prompt,--cwd,-e) are not forwarded as env varsAZD_EXT_DEBUGandAZD_EXT_TIMEOUTwith defaultsEnvironmentService —
GetValues,GetValue,SetValue:env_name/nameis optional; omitting it resolves to the current/default environment (shipped in Make env_name optional in EnvironmentService gRPC methods #6733, undocumented until now)Structured Error Handling — New section on
azdext.ServiceError, and clarifying thatWrapError/UnwrapErrorare internal; extension authors return*azdext.ServiceErrorfrom provider methods and Azure SDKazcore.ResponseErrorvalues are auto-detectedTable of Contents — Updated to surface the new sections
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.